home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-04 / xlib03.zip / XRECT.ASM < prev    next >
Assembly Source File  |  1993-04-05  |  18KB  |  408 lines

  1. ;-----------------------------------------------------------------------
  2. ; MODULE XRECT
  3. ;
  4. ; Rectangle functions all MODE X 256 Color resolutions
  5. ;
  6. ; Compile with Tasm.
  7. ; C callable.
  8. ;
  9. ;
  10. ; ****** XLIB - Mode X graphics library                ****************
  11. ; ******                                               ****************
  12. ; ****** Written By Themie Gouthas                     ****************
  13. ; ****** Aeronautical Research Laboratory              ****************
  14. ; ****** Defence Science and Technology Organisation   ****************
  15. ; ****** Australia                                     ****************
  16. ;
  17. ; egg@dstos3.dsto.gov.au
  18. ; teg@bart.dsto.gov.au
  19. ;-----------------------------------------------------------------------
  20.  
  21.  
  22. include xlib.inc
  23. include xrect.inc
  24.  
  25.  
  26.     .code
  27.  
  28. ; Plane masks for clipping left and right edges of rectangle.
  29.         LeftClipPlaneMask       db      00fh,00eh,00ch,008h
  30.     RightClipPlaneMask      db      00fh,001h,003h,007h
  31.  
  32. ;---------------------------------------------------------------------------
  33. ; Mode X (320x240, 256 colors) rectangle solid colour fill routine.
  34. ;
  35. ; Based on code originally published in DDJ Mag by M. Abrash
  36. ;
  37. ; with TASM 2. C near-callable as:
  38. ;
  39. ;    void x_rect_fill(int StartX, int StartY, int EndX, int EndY,
  40. ;       unsigned int PageBase, unsigne int color);
  41. ;
  42. ;
  43.  
  44.  
  45. _x_rect_fill proc
  46. ARG     StartX:word,StartY:word,EndX:word,EndY:word,PageBase:word,Color:word
  47.     push bp              ;preserve caller's stack frame
  48.     mov  bp,sp           ;point to local stack frame
  49.     push si              ;preserve caller's register variables
  50.     push di
  51.  
  52.         cld
  53.     mov  ax,[_ScrnLogicalByteWidth]
  54.     mul  [StartY]            ;offset in page of top rectangle scan line
  55.     mov  di,[StartX]
  56.     shr  di,1                ;X/4 = offset of first rectangle pixel in scan
  57.     shr  di,1                ; line
  58.     add  di,ax               ;offset of first rectangle pixel in page
  59.     add  di,[PageBase]       ;offset of first rectangle pixel in
  60.                      ; display memory
  61.     mov  ax,SCREEN_SEG       ;point ES:DI to the first rectangle
  62.     mov  es,ax               ; pixel's address
  63.     mov  dx,SC_INDEX         ;set the Sequence Controller Index to
  64.     mov  al,MAP_MASK         ; point to the Map Mask register
  65.     out  dx,al
  66.     inc  dx                  ;point DX to the SC Data register
  67.     mov  si,[StartX]
  68.     and  si,0003h                    ;look up left edge plane mask
  69.     mov  bh,cs:LeftClipPlaneMask[si]    ; to clip & put in BH
  70.     mov  si,[EndX]
  71.     and  si,0003h                    ;look up right edge plane
  72.     mov  bl,cs:RightClipPlaneMask[si]   ; mask to clip & put in BL
  73.  
  74.     mov  cx,[EndX]                   ;calculate # of addresses across rect
  75.     mov  si,[StartX]
  76.     cmp  cx,si
  77.     jle  @@FillDone                  ;skip if 0 or negative width
  78.     dec  cx
  79.     and  si,not 011b
  80.     sub  cx,si
  81.     shr  cx,1
  82.     shr  cx,1                 ;# of addresses across rectangle to fill - 1
  83.     jnz  @@MasksSet           ;there's more than one byte to draw
  84.     and  bh,bl                ;there's only one byte, so combine the left
  85.                                   ; and right edge clip masks
  86. @@MasksSet:
  87.     mov  si,[EndY]
  88.     sub  si,[StartY]            ;BX = height of rectangle
  89.     jle  @@FillDone             ;skip if 0 or negative height
  90.     mov  ah,byte ptr [Color]    ;color with which to fill
  91.     mov  bp,[_ScrnLogicalByteWidth]  ;stack frame isn't needed any more
  92.     sub  bp,cx                  ;distance from end of one scan line to start
  93.     dec  bp                     ; of next
  94. @@FillRowsLoop:
  95.     push cx                     ;remember width in addresses - 1
  96.     mov  al,bh                  ;put left-edge clip mask in AL
  97.     out  dx,al                  ;set the left-edge plane (clip) mask
  98.     mov  al,ah                  ;put color in AL
  99.         stosb                       ;draw the left edge
  100.     dec  cx                     ;count off left edge byte
  101.     js   @@FillLoopBottom       ;that's the only byte
  102.     jz   @@DoRightEdge          ;there are only two bytes
  103.     mov  al,00fh                ;middle addresses drawn 4 pixels at a pop
  104.     out  dx,al                  ;set the middle pixel mask to no clip
  105.     mov  al,ah                  ;put color in AL
  106.     rep  stosb                  ;draw middle addresses four pixels apiece
  107. @@DoRightEdge:
  108.     mov  al,bl                  ;put right-edge clip mask in AL
  109.     out  dx,al                  ;set the right-edge plane (clip) mask
  110.     mov  al,ah                  ;put color in AL
  111.         stosb                       ;draw the right edge
  112. @@FillLoopBottom:
  113.     add  di,bp                  ;point to start of the next scan line of
  114.                                     ; the rectangle
  115.     pop  cx                     ;retrieve width in addresses - 1
  116.     dec  si                     ;count down scan lines
  117.     jnz  @@FillRowsLoop
  118. @@FillDone:
  119.     pop  di                     ;restore caller's register variables
  120.     pop  si
  121.     pop  bp                     ;restore caller's stack frame
  122.         ret
  123. _x_rect_fill endp
  124.  
  125. ;---------------------------------------------------------------------------
  126. ; Mode X (320x240, 256 colors) rectangle 4x4 pattern fill routine.
  127. ; Upper left corner of pattern is always aligned to a multiple-of-4
  128. ; row and column. Works on all VGAs. Uses approach of copying the
  129. ; pattern to off-screen display memory, then loading the latches with
  130. ; the pattern for each scan line and filling each scan line four
  131. ; pixels at a time. Fills up to but not including the column at EndX
  132. ; and the row at EndY. No clipping is performed. All ASM code tested
  133. ;
  134. ;
  135. ; Based on code originally published in DDJ Mag by M. Abrash
  136. ;
  137. ;
  138. ;  C near-callable as:
  139. ;
  140. ;    void x_rect_pattern(int StartX, int StartY, int EndX, int EndY,
  141. ;       unsigned int PageBase, char far * Pattern);
  142.  
  143.  
  144.  
  145. _x_rect_pattern proc
  146. ARG     StartX:word,StartY:word,EndX:word,EndY:word,PageBase:word,Pattern:dword
  147. LOCAL   NextScanOffset:word,RectAddrWidth:word,Height:word=LocalStk
  148.     push bp                       ;preserve caller's stack frame
  149.     mov  bp,sp                    ;point to local stack frame
  150.     sub  sp,LocalStk              ;allocate space for local vars
  151.     push si                       ;preserve caller's register variables
  152.     push di
  153.         push ds
  154.         cld
  155.     mov  ax,SCREEN_SEG            ;point ES to display memory
  156.     mov  es,ax
  157.                       ;copy pattern to display memory buffer
  158.     lds  si,dword ptr [Pattern]   ;point to pattern to fill with
  159.     mov  di,PATTERN_BUFFER        ;point ES:DI to pattern buffer
  160.     mov  dx,SC_INDEX              ;point Sequence Controller Index to
  161.     mov  al,MAP_MASK              ; Map Mask
  162.     out  dx,al
  163.     inc  dx                       ;point to SC Data register
  164.     mov  cx,4                     ;4 pixel quadruplets in pattern
  165. @@DownloadPatternLoop:
  166.     mov  al,1                     ;
  167.     out  dx,al                    ;select plane 0 for writes
  168.         movsb                         ;copy over next plane 0 pattern pixel
  169.     dec  di                       ;stay at same address for next plane
  170.     mov  al,2                     ;
  171.     out  dx,al                    ;select plane 1 for writes
  172.         movsb                         ;copy over next plane 1 pattern pixel
  173.     dec  di                       ;stay at same address for next plane
  174.     mov  al,4                     ;
  175.     out  dx,al                    ;select plane 2 for writes
  176.         movsb                         ;copy over next plane 2 pattern pixel
  177.     dec  di                       ;stay at same address for next plane
  178.     mov  al,8                     ;
  179.     out  dx,al                    ;select plane 3 for writes
  180.         movsb                         ;copy over next plane 3 pattern pixel
  181.                                       ; and advance address
  182.         loop @@DownloadPatternLoop
  183.         pop  ds
  184.  
  185.     mov  dx,GC_INDEX              ;set the bit mask to select all bits
  186.     mov  ax,00000h+BIT_MASK       ; from the latches and none from
  187.     out  dx,ax                    ; the CPU, so that we can write the
  188.                                       ; latch contents directly to memory
  189.     mov  ax,[StartY]              ;top rectangle scan line
  190.     mov  si,ax
  191.     and  si,011b                  ;top rect scan line modulo 4
  192.     add  si,PATTERN_BUFFER        ;point to pattern scan line that
  193.                                       ; maps to top line of rect to draw
  194.     mov  dx,[_ScrnLogicalByteWidth]
  195.     mul  dx                       ;offset in page of top rect scan line
  196.     mov  di,[StartX]
  197.     mov  bx,di
  198.     shr  di,1             ;X/4 = offset of first rectangle pixel in scan
  199.     shr  di,1             ; line
  200.     add  di,ax                    ;offset of first rectangle pixel in page
  201.     add  di,[PageBase]            ;offset of first rectangle pixel in
  202.                                       ; display memory
  203.     and  bx,0003h                 ;look up left edge plane mask
  204.     mov  ah,cs:LeftClipPlaneMask[bx] ; to clip
  205.     mov  bx,[EndX]
  206.     and  bx,0003h                  ;look up right edge plane
  207.     mov  al,cs:RightClipPlaneMask[bx] ; mask to clip
  208.     mov  bx,ax                     ;put the masks in BX
  209.  
  210.     mov  cx,[EndX]                 ;calculate # of addresses across rect
  211.     mov  ax,[StartX]
  212.     cmp  cx,ax
  213.     jle  @@FillDone                ;skip if 0 or negative width
  214.     dec  cx
  215.     and  ax,not 011b
  216.     sub  cx,ax
  217.     shr  cx,1
  218.     shr  cx,1                 ;# of addresses across rectangle to fill - 1
  219.     jnz  @@MasksSet           ;there's more than one pixel to draw
  220.     and  bh,bl                ;there's only one pixel, so combine the left
  221.                                   ; and right edge clip masks
  222. @@MasksSet:
  223.     mov  ax,[EndY]
  224.     sub  ax,[StartY]          ;AX = height of rectangle
  225.     jle  @@FillDone           ;skip if 0 or negative height
  226.     mov  [Height],ax
  227.     mov  ax,[_ScrnLogicalByteWidth]
  228.     sub  ax,cx                ;distance from end of one scan line to start
  229.     dec  ax                   ; of next
  230.     mov  [NextScanOffset],ax
  231.     mov  [RectAddrWidth],cx   ;remember width in addresses - 1
  232.     mov  dx,SC_INDEX+1        ;point to Sequence Controller Data reg
  233.                                   ; (SC Index still points to Map Mask)
  234. @@FillRowsLoop:
  235.     mov  cx,[RectAddrWidth]   ;width across - 1
  236.     mov  al,es:[si]           ;read display memory to latch this scan
  237.                                   ; line's pattern
  238.     inc  si                   ;point to the next pattern scan line, wrapping
  239.     jnz  short @@NoWrap       ; back to the start of the pattern if
  240.     sub  si,4                 ; we've run off the end
  241. @@NoWrap:
  242.     mov  al,bh                ;put left-edge clip mask in AL
  243.     out  dx,al                ;set the left-edge plane (clip) mask
  244.         stosb                     ;draw the left edge (pixels come from latches;
  245.                                   ; value written by CPU doesn't matter)
  246.     dec  cx                   ;count off left edge address
  247.     js   @@FillLoopBottom     ;that's the only address
  248.     jz   @@DoRightEdge        ;there are only two addresses
  249.     mov  al,00fh              ;middle addresses drawn 4 pixels at a pop
  250.     out  dx,al                ;set middle pixel mask to no clip
  251.     rep  stosb                ;draw middle addresses four pixels apiece
  252.                                   ; (from latches; value written doesn't matter)
  253. @@DoRightEdge:
  254.     mov  al,bl                ;put right-edge clip mask in AL
  255.     out  dx,al                ;set the right-edge plane (clip) mask
  256.         stosb                     ;draw the right edge (from latches; value
  257.                                   ; written doesn't matter)
  258. @@FillLoopBottom:
  259.     add  di,[NextScanOffset]  ;point to the start of the next scan
  260.                   ; line of the rectangle
  261.     dec  word ptr [Height]    ;count down scan lines
  262.     jnz  @@FillRowsLoop
  263. @@FillDone:
  264.     mov  dx,GC_INDEX+1        ;restore the bit mask to its default,
  265.     mov  al,0ffh              ; which selects all bits from the CPU
  266.     out  dx,al                ; and none from the latches (the GC
  267.                   ; Index still points to Bit Mask)
  268.  
  269.     pop  di                   ;restore caller's register variables
  270.     pop  si
  271.     mov  sp,bp                ;discard storage for local variables
  272.     pop  bp                   ;restore caller's stack frame
  273.         ret
  274. _x_rect_pattern endp
  275.  
  276. ;-----------------------------------------------------------------------
  277. ; Mode X (320x240, 256 colors) display memory to display memory copy
  278. ; routine. Left edge of source rectangle modulo 4 must equal left edge
  279. ; of destination rectangle modulo 4. Works on all VGAs. Uses approach
  280. ; of reading 4 pixels at a time from the source into the latches, then
  281. ; writing the latches to the destination. Copies up to but not
  282. ; including the column at SrcEndX and the row at SrcEndY. No
  283. ; clipping is performed. Results are not guaranteed if the source and
  284. ; destination overlap.
  285. ;
  286. ;
  287. ; Based on code originally published in DDJ Mag by M. Abrash
  288. ;
  289. ;C near-callable as:
  290. ;    void x_cp_vid_rect(int SrcStartX, int SrcStartY,
  291. ;       int SrcEndX, int SrcEndY, int DestStartX,
  292. ;       int DestStartY, unsigned int SrcPageBase,
  293. ;       unsigned int DestPageBase, int SrcBitmapWidth,
  294. ;       int DestBitmapWidth);
  295.  
  296. _x_cp_vid_rect proc
  297.     ARG SrcStartX:word,SrcStartY:word,SrcEndX:word,SrcEndY:word,DestStartX:word,DestStartY:word,SrcPageBase:word,DestPageBase:word,SrcBitmapW:word,DestBitmapW:word
  298.     LOCAL SrcNextOffs:word,DestNextOffs:word,RectAddrW:word,Height:word=LocalStk
  299.     push    bp                  ;preserve caller's stack frame
  300.     mov     bp,sp               ;point to local stack frame
  301.     sub     sp,LocalStk         ;allocate space for local vars
  302.     push    si                  ;preserve caller's register variables
  303.         push    di
  304.         push    ds
  305.  
  306.         cld
  307.     mov     dx,GC_INDEX         ;set the bit mask to select all bits
  308.     mov     ax,00000h+BIT_MASK  ; from the latches and none from
  309.     out     dx,ax               ; the CPU, so that we can write the
  310.                     ; latch contents directly to memory
  311.     mov     ax,SCREEN_SEG       ;point ES to display memory
  312.         mov     es,ax
  313.     mov     ax,[DestBitmapW]
  314.     shr     ax,2                ;convert to width in addresses
  315.     mul     [DestStartY]        ;top dest rect scan line
  316.     mov     di,[DestStartX]
  317.     shr     di,2                ;X/4 = offset of first dest rect pixel in
  318.                     ; scan line
  319.     add     di,ax               ;offset of first dest rect pixel in page
  320.     add     di,[DestPageBase]   ;offset of first dest rect pixel
  321.                     ; in display memory
  322.     mov     ax,[SrcBitmapW]
  323.     shr     ax,2                ;convert to width in addresses
  324.     mul     [SrcStartY]      ;top source rect scan line
  325.     mov     si,[SrcStartX]
  326.         mov     bx,si
  327.     shr     si,2              ;X/4 = offset of first source rect pixel in
  328.                   ; scan line
  329.     add     si,ax             ;offset of first source rect pixel in page
  330.     add     si,[SrcPageBase]  ;offset of first source rect
  331.                   ; pixel in display memory
  332.     and     bx,0003h                     ;look up left edge plane mask
  333.     mov     ah,cs:LeftClipPlaneMask[bx]  ; to clip
  334.     mov     bx,[SrcEndX]
  335.     and     bx,0003h                     ;look up right edge plane
  336.     mov     al,cs:RightClipPlaneMask[bx] ; mask to clip
  337.     mov     bx,ax                        ;put the masks in BX
  338.  
  339.     mov     cx,[SrcEndX]              ;calculate # of addresses across
  340.     mov     ax,[SrcStartX]            ; rect
  341.         cmp     cx,ax
  342.     jle     @@CopyDone                   ;skip if 0 or negative width
  343.         dec     cx
  344.         and     ax,not 011b
  345.         sub     cx,ax
  346.     shr     cx,2             ;# of addresses across rectangle to copy - 1
  347.     jnz     @@MasksSet       ;there's more than one address to draw
  348.     and     bh,bl            ;there's only one address, so combine the left
  349.                  ; and right edge clip masks
  350. @@MasksSet:
  351.     mov     ax,[SrcEndY]
  352.     sub     ax,[SrcStartY]     ;AX = height of rectangle
  353.     jle     @@CopyDone         ;skip if 0 or negative height
  354.     mov     [Height],ax
  355.     mov     ax,[DestBitmapW]
  356.     shr     ax,2               ;convert to width in addresses
  357.     sub     ax,cx              ;distance from end of one dest scan line
  358.     dec     ax                 ; to start of next
  359.     mov     [DestNextOffs],ax
  360.     mov     ax,[SrcBitmapW]
  361.     shr     ax,2               ;convert to width in addresses
  362.     sub     ax,cx              ;distance from end of one source scan line
  363.     dec     ax                 ; to start of next
  364.     mov     [SrcNextOffs],ax
  365.     mov     [RectAddrW],cx     ;remember width in addresses - 1
  366.     mov     dx,SC_INDEX+1      ;point to Sequence Controller Data reg
  367.                    ; (SC Index still points to Map Mask)
  368.     mov     ax,es              ;DS=ES=screen segment for MOVS
  369.         mov     ds,ax
  370. @@CopyRowsLoop:
  371.     mov     cx,[RectAddrW]     ;width across - 1
  372.     mov     al,bh              ;put left-edge clip mask in AL
  373.     out     dx,al              ;set the left-edge plane (clip) mask
  374.     movsb                      ;copy the left edge (pixels go through
  375.                    ; latches)
  376.     dec     cx                 ;count off left edge address
  377.     js      @@CopyLoopBottom   ;that's the only address
  378.     jz      @@DoRightEdge      ;there are only two addresses
  379.     mov     al,00fh            ;middle addresses are drawn 4 pix per go
  380.     out     dx,al              ;set the middle pixel mask to no clip
  381.     rep     movsb              ;draw the middle addresses four pix per go
  382.                    ; (pixels copied through latches)
  383. @@DoRightEdge:
  384.         mov     al,bl   ;put right-edge clip mask in AL
  385.         out     dx,al   ;set the right-edge plane (clip) mask
  386.         movsb           ;draw the right edge (pixels copied through
  387.                         ; latches)
  388. @@CopyLoopBottom:
  389.     add     si,[SrcNextOffs]   ;point to the start of
  390.     add     di,[DestNextOffs]  ; next source & dest lines
  391.     dec     word ptr [Height]  ;count down scan lines
  392.     jnz     @@CopyRowsLoop
  393. @@CopyDone:
  394.     mov     dx,GC_INDEX+1   ;restore the bit mask to its default,
  395.         mov     al,0ffh         ; which selects all bits from the CPU
  396.         out     dx,al           ; and none from the latches (the GC
  397.                                 ; Index still points to Bit Mask)
  398.         pop     ds
  399.     pop     di              ;restore caller's register variables
  400.         pop     si
  401.     mov     sp,bp           ;discard storage for local variables
  402.     pop     bp              ;restore caller's stack frame
  403.         ret
  404. _x_cp_vid_rect  endp
  405.  
  406.     end
  407.  
  408.